/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.diego.games.tetris.layer;

import br.diego.games.tetris.interfaces.IBlock;

import javax.microedition.lcdui.game.Layer;
import javax.microedition.lcdui.game.TiledLayer;

/**
 *
 * @author diego
 */
public class Tetris {

    public Tetris() {
    }

    public interface Event {

        public void onEvent(int code);
    }
    public static final int BLOCK_PREVIEW = -1;
    public static final int COLISAO_HORIZONTAL = 0;
    public static final int COLISAO_VERTICAL = 1;
    public static final int COLISAO_BLOCK = 2;
    public static final int CLEAR_LINE = 3;
    public static final int ROTATE = 4;
    public static final int START = 5;
    public static final int OVER = 6;
    private Event event;
    private static int BG_COLOR = Constant.NO_COLOR;
    private static final int[] lines = {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR};
    private IBlock iTitles;
    private boolean gameOver = false;
    private int[] cels = {-1, 4};
    int[][] tiles = {
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR},
        {BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR, BG_COLOR}
    };
    public TiledLayer layer;

    public int[][] getTiles() {
        return tiles;
    }

    public boolean gameOver() {
        return this.gameOver;
    }

    public void clear() {
        int mRow = this.tiles.length;
        int mCol = this.iTitles.getTiles()[0].length;
        for (int row = 0; row < mRow; row++) {
            boolean rowIsColor = true;
            for (int col = 0; col < mCol; col++) {
                if (tiles[row][col] == Constant.NO_COLOR) {
                    rowIsColor = false;
                    break;
                }
            }
            if (rowIsColor) {
                for (int r = row; r > 0; r--) {
                    tiles[r] = tiles[r - 1];
                }
                tiles[0] = lines;
                this.exercuteEvent(Tetris.CLEAR_LINE);
            }
        }
    }

    public void add(IBlock iTitles) {
        this.iTitles = iTitles;
        insert(cels[0], cels[1]);
    }

    public synchronized boolean checked(int x, int y) {
        final int[][] t = this.iTitles.getTiles();
        final int color = this.iTitles.color();
        int mRow = x + t.length;
        int mCol = y + this.iTitles.getTiles()[0].length;
        for (int row = x; row < mRow; row++) {
            for (int col = y; col < mCol; col++) {
                if ((col > this.tiles.length) || (col < 0)) {
                    this.exercuteEvent(Tetris.COLISAO_VERTICAL);
                   // return false;
                }

                if ((row > 0)) {
                    if ((tiles[row][col] != BG_COLOR)) {
                        if (tiles[row][col] != color) {
                            this.exercuteEvent(Tetris.COLISAO_BLOCK);
                            return false;
                        }
                    }
                }
            }
        }
        return true;
    }

    public void rotate() {
        final int[][] t = this.iTitles.getTiles();
        int mRow = t.length;
        int mCol = this.iTitles.getTiles()[0].length;
        final int[][] invert = new int[mCol][mRow];

        for (int row = 0; row < mRow; row++) {
            for (int col = 0; col < mCol; col++) {
                invert[col][row] = t[row][col];
            }
        }
        this.iTitles.setTiles(invert);
        this.exercuteEvent(Tetris.ROTATE);
    }

    public void remove(int x, int y) {
        final int[][] t = this.iTitles.getTiles();
        int mRow = x + t.length;
        int mCol = y + this.iTitles.getTiles()[0].length;
        for (int row = x; row < mRow; row++) {
            for (int col = y; col < mCol; col++) {
                if (!(row < 0)) {
                    tiles[row][col] = BG_COLOR;
                }
            }
        }

    }

    public boolean insert(int x, int y) {
        final int[][] t = this.iTitles.getTiles();
        int mRow = x + t.length;
        int mCol = y + this.iTitles.getTiles()[0].length;
        for (int row = x; row < mRow; row++) {
            for (int col = y; col < mCol; col++) {
                if (col >= this.tiles[0].length) {
                    return false;
                }
                if (!(row < 0)) {
                    tiles[row][col] = t[row - x][col - y];
                }
            }
        }
        return true;
    }

    public void exercuteEvent(int code) {
        if (this.event == null) {
            return;
        }
        this.event.onEvent(code);

    }

    public void down() {
        int x = this.cels[0];
        int y = this.cels[1];
        if (checked(x + 1, y)) {
            remove(x, y);
            insert(++x, y);
            this.cels[0] = x;
        }

    }

    public void rigth() {
        int x = this.cels[0];
        int y = this.cels[1];
        if (checked(x, y + 1)) {
            remove(x, y);
            insert(x, ++y);
            this.cels[1] = y;
        }
    }

    public void left() {
        int x = this.cels[0];
        int y = this.cels[1];
        if (checked(x, y - 1)) {
            remove(x, y);
            insert(x, --y);
            this.cels[1] = y;
        }
    }

    public void setTiles(int[][] tiles) {
        this.tiles = tiles;
    }

    public Layer getTiledLayer() throws java.io.IOException {
        int mRow = this.tiles.length;
        int mCol = this.tiles[0].length;
        if (layer == null) {
            layer = new TiledLayer(mCol, mRow, Constant.getImage(), Constant.HEIGHT, Constant.WIDTH);
            this.exercuteEvent(Tetris.START);

        }

        for (int row = 0; row < mRow; row++) {
            for (int col = 0; col < mCol; col++) {
                layer.setCell(col, row, tiles[row][col]);
            }
        }
        return layer;
    }

    /**
     * @param event the event to set
     */
    public void onEvent(Event event) {
        this.event = event;
    }

    public String toString() {
        String buffer = "";
        int mRow = this.tiles.length;
        int mCol = this.tiles[0].length;
        for (int row = 0; row < mRow; row++) {
            for (int col = 0; col < mCol; col++) {
                buffer = buffer + "[ " + (tiles[row][col]) + " ]";
            }
            buffer = buffer + '\n';
        }
        return "_____________________________________________\n" + buffer;
    }
}
